# -*- coding: utf-8 -*- #
"""
Time                2023/04/06 13:13
Author:             mingfeng (SunnyQjm)
Email               mfeng@linux.alibaba.com
File                framework_plug_mag.py
Description:
"""
import threading
from typing import List, Optional, Type
from abc import abstractmethod, ABC
from .config_parser import ConfigParser


class StoppableThread(threading.Thread):
    """Thread class with a stop() method
    The thread itself has to check regularly for the stopped() condition.
    """

    def __init__(self, group=None, target=None, **kwargs):
        super().__init__(group, target, **kwargs)
        self._stop_event = threading.Event()

    def stop(self):
        """Notify the thread to exit（async）"""
        self._stop_event.set()

    def stopped(self):
        """Determine whether the thread exits."""
        return self._stop_event.is_set()


class FrameworkPluginBase(ABC):

    @abstractmethod
    def start(self):
        pass

    @abstractmethod
    def stop(self):
        pass

    @abstractmethod
    def join(self, timeout: Optional[float] = None):
        pass


class FrameworkPlugMag(StoppableThread):
    """A class for managing plugins in the framework layer
    """

    def __init__(self, config: ConfigParser) -> None:
        super().__init__(target=self.run)
        self.setDaemon(True)
        self._config = config
        self._plugins: List[FrameworkPluginBase] = []

    def load_plugin(self, plugin: FrameworkPluginBase):
        self._plugins.append(plugin)
        return self

    def load_plugin_cls(self, plugin_cls: Type[FrameworkPluginBase]):
        self._plugins.append(plugin_cls(self._config))
        return self

    def run(self):
        for plugin in self._plugins:
            plugin.start()

    def start(self) -> None:
        return super().start()

    def join(self, timeout: Optional[float] = None) -> None:
        for plugin in self._plugins:
            plugin.join(timeout)
        return super().join(timeout)
